<template>
  <div class="malffunction-chart-wrapper">
    <!-- <button @click="initPage([0])">图一</button>
    <button @click="initPage([1])">图二</button>
    <button @click="initPage([0, 1])">图一二</button>
    <button @click="initPage([0, 2])">图一三</button>
    <button @click="initPage()">还原</button> -->
    <div ref="malfunctionChartRef" class="malffunction-chart" />
    <transition name="fade">
      <div v-show="showTitleEllipsis" class="title-card" :style="cardStyle">
        {{ titleEllipsis }}
      </div>
    </transition>
  </div>
</template>

<script setup>
  import { ref, onMounted, onBeforeUnmount } from "vue";
  import { init, graphic } from "echarts";
  import dayjs from "dayjs";
  import { intervalColor } from "./config";

  import mockData from "./mock";
  import useChart from "./useChart";

  const emit = defineEmits(["changeChartPosition"]);
  const props = defineProps({
    showSampleStatusRiskTree: {
      type: Boolean,
      default: false,
    },
    sampleData: {
      type: Object,
      default: () => mockData,
    },
    selectedStrategyType: {
      type: String,
      default: "",
    },
  });

  let lineChart = null;
  const {
    xStart,
    xEnd,
    canvasHeight,
    titleWidth,
    containerHeight,
    canvasWidth,
    lineData,
    circleData,
    barData,
    lineDataOriginal,
    circleDataOriginal,
    barDataOriginal,
    originalStrategyData,
    optimizeRecommendationsData,
    zoomStart,
    zoomEnd,
    getFullCicleOpt,
  } = useChart();
  const malfunctionChartRef = ref();
  const titleEllipsis = ref("");
  const showTitleEllipsis = ref(false);
  const cardStyle = ref({
    top: 0,
    left: 0,
  });

  const zoomStartCopy = ref(0);
  const zoomEndCopy = ref(0);

  const targetAction = ref({
    optimize: {
      isSelectedIcon: -1,
      clickCircleTime: 0,
    },
    original: {
      isSelectedIcon: -1,
      clickCircleTime: 0,
    },
  });

  // 判断可视区域
  const judgeVisualArea = (item, flag, ind) => {
    if (flag && ind > -1) {
      // 判断当前选中的点位在不在当前可视区域内
      if (item.strategyOccurrenceTime < zoomStart.value) {
        // 如果当前点位的时间小于开始时间
        let subtractNum = dayjs(zoomStart.value).diff(
          item.strategyOccurrenceTime,
          "day"
        );
        zoomStart.value = dayjs(zoomStart.value)
          .subtract(subtractNum, "day")
          .valueOf();
        zoomEnd.value = dayjs(zoomEnd.value)
          .subtract(subtractNum, "day")
          .valueOf();
        zoomEndCopy.value = zoomEnd.value;
        zoomStartCopy.value = zoomStart.value;
      } else if (item.strategyOccurrenceTime > zoomEnd.value) {
        // 如果当前点位的时间大于开始时间
        let subtractNum = dayjs(item.strategyOccurrenceTime).diff(
          zoomStart.value,
          "day"
        );
        zoomStart.value = dayjs(zoomStart.value)
          .add(subtractNum, "day")
          .valueOf();
        zoomEnd.value = dayjs(zoomEnd.value).add(subtractNum, "day").valueOf();
        // 如果最右侧的值比最大时间还大，则直接等于最大时间
        if (zoomEnd.value > xEnd.value) zoomEnd.value = xEnd.value;
        if (zoomStart.value > zoomEnd.value) zoomStart.value = zoomEnd.value;
        zoomEndCopy.value = zoomEnd.value;
        zoomStartCopy.value = zoomStart.value;
      }

      const obj = props?.sampleData?.expiryInfos.find(
        (it) => it.endTime === item.strategyOccurrenceTime
      );
      const params = {
        startDate: item.strategyOccurrenceTime,
        endDate: item.strategyOccurrenceTime,
      };
      if (obj) {
        params.startDate = obj.startTime;
        params.endDate = obj.endTime;
      }

      // 确定好点位之后拉起隐患树
      emit("changeChartPosition", params);
    }
  };

  // 初始化数据
  const initData = () => {
    lineData.value = props?.sampleData?.expiryInfos?.map((item) => ({
      value: [item.startTime, item.endTime, item.expiryDuration, 1], // 开始时间，结束时间
      chartType: "line",
    }));
    lineDataOriginal.value = props?.sampleData?.expiryInfos1?.map((item) => ({
      value: [item.startTime, item.endTime, item.expiryDuration, 1], // 开始时间，结束时间
      chartType: "line",
    }));
    barData.value = props?.sampleData?.barData?.map((item) => {
      const itemColor = intervalColor[item.intervalType];
      return {
        value: [item.startTime, item.endTime, item.expiryDuration, 1], // 开始时间，结束时间
        itemStyle: {
          opacity: 0.4,
          color: new graphic.LinearGradient(0, 0, 0, 1, [
            {
              offset: 0,
              color: itemColor[0],
            },
            {
              offset: 1,
              color: itemColor[1],
            },
          ]),
        },
        chartType: "bar",
      };
    });
    barDataOriginal.value = props?.sampleData?.barData1?.map((item) => {
      const itemColor = intervalColor[item.intervalType];
      return {
        value: [item.startTime, item.endTime, item.expiryDuration, 1], // 开始时间，结束时间
        itemStyle: {
          opacity: 0.4,
          color: new graphic.LinearGradient(0, 0, 0, 1, [
            {
              offset: 0,
              color: itemColor[0],
            },
            {
              offset: 1,
              color: itemColor[1],
            },
          ]),
        },
        chartType: "bar",
      };
    });
    originalStrategyData.value = props?.sampleData?.originalStrategy?.map(
      (item) => {
        const { startTime, endTime, pointTime } = item;
        return {
          value: [startTime, endTime, pointTime], // 原有策略
        };
      }
    );
    optimizeRecommendationsData.value =
      props?.sampleData?.optimizeRecommendations?.map((item) => {
        const { startTime, endTime, pointTime } = item;
        return {
          value: [startTime, endTime, pointTime], // 优化推荐
        };
      });
    function getCircleData(data) {
      return data?.map((item) => {
        let flag = false;
        // 首先判断是否是点击
        const ind = item.strategyTypes.findIndex(
          (it) => it === props.selectedStrategyType
        );
        if (
          targetAction.value.optimize.clickCircleTime &&
          targetAction.value.optimize.clickCircleTime ===
            item.strategyOccurrenceTime
        ) {
          // 如果有指定锚点直接用
          flag =
            targetAction.value.optimize?.isSelectedIcon === -1 ? true : false;
        } else {
          flag =
            targetAction.value.optimize.clickCircleTime === 0 &&
            targetAction.value.optimize.isSelectedIcon === -1 &&
            ind > -1
              ? true
              : false;
        }
        if (flag && ind > -1) {
          targetAction.value.optimize.isSelectedIcon = ind;
          judgeVisualArea(item, flag, ind);
        }
        // 开始点位，结束点位，策略类型是否标红(当为“退化更换”的时候需要标红)，首个点位
        const indType = item.strategyTypes.findIndex(
          (it) => it === "DEGRADED_REPLACE"
        );
        const arr = [item.strategyOccurrenceTime, 0, indType > -1, flag];
        return {
          circleType: "optimize",
          chartType: "circle",
          value: arr,
        };
      });
    }
    // 筛选出符合当前策略类型的第一个
    circleData.value = getCircleData(props?.sampleData?.strategyInfos);
    circleDataOriginal.value = props?.sampleData?.strategyInfos1?.map(
      (item) => {
        let flag = false;
        // 首先判断是否是点击
        const ind = item.strategyTypes.findIndex(
          (it) => it === props.selectedStrategyType
        );
        if (
          targetAction.value.original.clickCircleTime &&
          targetAction.value.original.clickCircleTime ===
            item.strategyOccurrenceTime
        ) {
          // 如果有指定锚点直接用
          flag =
            targetAction.value.original.isSelectedIcon === -1 ? true : false;
        } else {
          flag =
            targetAction.value.original.clickCircleTime === 0 &&
            targetAction.value.original.isSelectedIcon === -1 &&
            ind > -1
              ? true
              : false;
        }
        if (flag && ind > -1) {
          targetAction.value.original.isSelectedIcon = ind;
          judgeVisualArea(item, flag, ind);
        }
        // 开始点位，结束点位，策略类型是否标红(当为“退化更换”的时候需要标红)，首个点位
        const indType = item.strategyTypes.findIndex(
          (it) => it === "DEGRADED_REPLACE"
        );
        const arr = [item.strategyOccurrenceTime, 0, indType > -1, flag];
        return {
          chartType: "circle",
          circleType: "original",
          value: arr,
        };
      }
    );
  };

  const setTitleWidth = () => {
    canvasWidth.value = malfunctionChartRef.value?.offsetWidth;
    canvasHeight.value = malfunctionChartRef.value?.offsetHeight;
    titleWidth.value = canvasWidth.value - 740; //容器宽度-图例宽度
    containerHeight.value = (canvasHeight.value - 200) / 2;
  };
  // 监听页面
  const resize = () => {
    setTitleWidth();
    if (lineChart) lineChart.resize();
    lineChart.setOption({
      title: [
        {
          textStyle: {
            width: titleWidth.value,
          },
        },
      ],
    });
  };

  // 初始化表格
  const initChart = () => {
    lineChart = init(malfunctionChartRef.value, null, {
      renderer: "canvas",
      useDirtyRect: false,
    });
    window.addEventListener("resize", resize);
    resize();
  };
  // 触摸标题
  const actionTitle = (params) => {
    const offsetX = params.event.offsetX;
    const offsetY = params.event.offsetY;
    const target = params.event.target;
    const parent = target.parent;
    const targetText = target.style?.text;
    const richObj = parent.style?.rich;
    const parentText = parent.style.text;
    let targetKey = "";
    if (!targetText) return;
    if (!targetText?.includes("...")) return;
    for (let key in richObj) {
      if (richObj[key].text === targetText) targetKey = key;
    }
    const reg = /(?<=\{)(.+?)(?=\})/g;
    const strArr = parentText.match(reg);
    const arr = strArr.map((item) => {
      const key = item.split("|")[0];
      const value = item.split("|")[1];
      return {
        key,
        value,
      };
    });
    let str = arr.find((x) => x.key === targetKey)?.value;
    let index = arr.findIndex((x) => x.key === targetKey);
    if (index > -1) {
      let a = arr.splice(index + 1);
      let b = a.map((x) => x.value).join(" ");
      str += b;
    }
    titleEllipsis.value = str;
    cardStyle.value.left = `${offsetX + 20}px`;
    cardStyle.value.top = `${offsetY + 20}px`;
    if (str) {
      showTitleEllipsis.value = true;
    }
  };

  const intervalDay = ref(0); // 时间间隔

  // 渲染
  const render = (chartNum) => {
    if (!lineChart) initChart();
    const chartOption = getFullCicleOpt(chartNum);
    if (chartOption) {
      lineChart.setOption(chartOption);
      setTimeout(() => {
        resize();
      }, 100);
      lineChart.off("click");
      lineChart.on("click", (val) => {
        if (val.componentType === "title") return;
        if (val.data?.chartType === "line") {
          console.log("折线：", val.data);
        }
        if (val.data.chartType === "circle") {
          const startDate = val.value[0];
          const endDate = val?.value[1] || val.value[0];
          targetAction.value[val.data?.circleType].isSelectedIcon = -1;
          // 记录点击锚点的时间,用作初始化的时候定位
          targetAction.value[val.data?.circleType].clickCircleTime = !val
            ?.value[1]
            ? startDate
            : endDate;
          if (val.data?.circleType === "optimize") {
            targetAction.value.original.isSelectedIcon = -1;
            targetAction.value.original.clickCircleTime = 0;
            initPage([0]);
          }
          if (val.data?.circleType === "original") {
            targetAction.value.optimize.isSelectedIcon = -1;
            targetAction.value.optimize.clickCircleTime = 0;
            initPage([1]);
          }
          const obj = props?.sampleData?.expiryInfos.find(
            (it) => it.endTime === endDate
          );
          const params = { startDate, endDate };
          if (obj) {
            params.startDate = obj.startTime;
            params.endDate = obj.endTime;
          }
          // 点击之后选中
          emit("changeChartPosition", params);
        } else {
          initPage();
        }
      });
      lineChart.on("dataZoom", (e) => {
        const startDay = Math.floor(intervalDay.value * (e.start / 100));
        const endDay = Math.ceil(intervalDay.value * (1 - e.end / 100));
        zoomStartCopy.value = dayjs(xStart.value)
          .add(startDay, "day")
          .valueOf();
        zoomEndCopy.value = dayjs(xEnd.value).subtract(endDay, "day").valueOf();
        zoomEnd.value = zoomEndCopy.value;
        zoomStart.value = zoomStartCopy.value;
      });
      lineChart.on("mouseover", function (params) {
        if (params.componentType === "title") {
          actionTitle(params);
        }
       
      });
      lineChart.on("mouseout", function (params) {
        showTitleEllipsis.value = false;
       
      });
    }
  };

  const initPage = (chartNum) => {
    initData();
    setTimeout(() => {
      if (lineChart) lineChart.clear();
      render(chartNum);
    }, 200);
  };

  onMounted(() => {
    xStart.value = props.sampleData.rulerMinTime;
    xEnd.value = props.sampleData.rulerMaxTime;
    zoomStart.value = zoomStartCopy.value || props.sampleData.rulerMinTime;
    zoomEnd.value = zoomEndCopy.value || props.sampleData.rulerMaxTime;
    zoomStartCopy.value = zoomStart.value;
    zoomEndCopy.value = zoomEnd.value;
    intervalDay.value =
      intervalDay.value || dayjs(zoomEnd.value).diff(zoomStart.value, "day");
    initPage();
  });
  onBeforeUnmount(() => {
    circleData.value = [];
    circleDataOriginal.value = [];
    targetAction.value.optimize.isSelectedIcon = -1;
    targetAction.value.original.isSelectedIcon = -1;
    xStart.value = 0;
    xEnd.value = 0;
    zoomStart.value = 0;
    zoomStartCopy.value = 0;
    zoomEndCopy.value = 0;
    intervalDay.value = 0;
    targetAction.value.optimize.clickCircleTime = 0;
    targetAction.value.original.clickCircleTime = 0;
  });
</script>
<style lang="less">
  .echarts-tooltip-content {
    font-size: 18px;
    color: #626c78;

    .hiding-duration {
      margin-top: 8px;
      display: flex;
      gap: 16px;
      .name {
        width: 108px;
      }
      .time {
        color: #1b2129;
      }
    }
  }
</style>
<style lang="less" scoped>
  @import "./index.less";
</style>
